package com.highgain.displacementtrend.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.highgain.displacementtrend.entity.Device;
import com.highgain.displacementtrend.entity.Result;
import com.highgain.displacementtrend.entity.DeviceData;
import com.highgain.displacementtrend.mapper.DeviceDataMapper;
import com.highgain.displacementtrend.service.UploadInfoService;
import com.highgain.displacementtrend.service.DisplacementService;
import com.highgain.displacementtrend.util.DateUtil;
import com.highgain.displacementtrend.util.PageView;
import org.apache.logging.log4j.util.Strings;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author zhanglifeng
 * @date 2021/04/13 19:22
 **/
@Service
public class DisplacementServiceImpl extends ServiceImpl<DeviceDataMapper, DeviceData> implements DisplacementService {
    private static final Logger logger = LoggerFactory.getLogger(DisplacementServiceImpl.class);

    @Resource
    private UploadInfoService uploadInfoService;
    
    @Override
    public Result dealData(String dataType, String deviceId , String data) {
        Result result = new Result();
        JSONObject objJson = JSON.parseObject(data);
        if (objJson == null) {
            return Result.error("json格式错误！").data(JSON.parseObject("{\"deviceId\":\"" + deviceId +"\"}"));
        }

        switch (dataType) {
            case "1":
            case "2":
                List<Map<String, Object>> mapList = getListFromJson(dataType, data);
                boolean finalResult = true;
                boolean[] multiResult = new boolean[mapList.size()];
                for (int i = 0; i < mapList.size(); i ++) {
                    multiResult[i] = dealMapData(mapList.get(i));
                }

                for (boolean b:multiResult) {
                    finalResult = finalResult && b;
                }

                if(finalResult){
                    result = Result.ok("插入数据成功！").data(JSON.parseObject("{\"deviceId\":\"" + deviceId +"\"}"));
                }else{
                    result = Result.ok("插入数据失败！请检查数据格式！").data(JSON.parseObject("{\"deviceId\":\"" + deviceId +"\"}"));
                }
                break;
            default:
                break;
        }
        return result;
    }

    @Override
    public PageView<DeviceData> queryDeviceData(PageView<DeviceData> pageView, Device device) {
        Page<DeviceData> page = new Page<>(pageView.getPageNow(), pageView.getPageSize());
        IPage<DeviceData> dataIPage = baseMapper.queryDeviceData(page, device);
        pageView.setRowCount(((int) dataIPage.getTotal()));
        pageView.setRecords(dataIPage.getRecords());
        return pageView;
    }

    @Override
    public Result queryAll(Device device) {
        return Result.ok("").data(baseMapper.queryAll(device));
    }

    /**
     * 将上传的json字符串进行解析并存到map列表里
     * @author zhanglifeng
     * @date 2021/04/13 10:29
     * @param type 上传类型：1. 实时数据， 2. 历史数据
     * @param data  数据json字符串
     * @return java.util.List<java.util.Map<java.lang.String,java.lang.Object>>
     */
    private List<Map<String, Object>> getListFromJson(String type, String data){
        List<Map<String, Object>> mapList = new ArrayList<>();
        Map mapTypes =  JSON.parseObject(data);
        for (Object obj : mapTypes.keySet()){
            HashMap<String, Object> myMap = new HashMap<>(16);
            myMap.put("deviceId", obj);
            Map map =  (Map)mapTypes.get(obj);
            for (Object secondObj : map.keySet()) {
                myMap.put("dataFlow", secondObj);
                if(map.get(secondObj)  instanceof JSONObject){
                    Map innerMap = (Map)map.get(secondObj);
                    for (Object thirdObj: innerMap.keySet()) {
                        if(innerMap.get(thirdObj) instanceof JSONObject){
                            myMap.put("time", thirdObj);
                            Map fourMap = (Map)innerMap.get(thirdObj);
                            for (Object fourObj: fourMap.keySet()) {
                                myMap.put((String)fourObj, innerMap.get(thirdObj));
                            }
                        }else{
                            if("2".equals(type)){
                                myMap.put("time", thirdObj);
                                myMap.put("value", innerMap.get(thirdObj));
                            }else if("1".equals(type)){
                                if(DateUtil.isDateFormat((String)thirdObj) != null){
                                    myMap.put("time", thirdObj);
                                    myMap.put("value", innerMap.get(thirdObj));
                                }else{
                                    myMap.put("time", DateUtil.getCurrentDayTime());
                                    myMap.put((String)thirdObj, innerMap.get(thirdObj));
                                }
                            }
                        }
                    }
                }else{
                    myMap.put("time", DateUtil.getCurrentDayTime());
                    myMap.put("value", map.get(secondObj));
                }

            }
            mapList.add(myMap);
        }

        return mapList;
    }

    /**
     * 处理map中的数据
     * @author zhanglifeng
     * @date 2021/04/13 19:54
     * @param map 
     * @return boolean
     */
    private boolean dealMapData(Map<String, Object> map){
        if(map.get("deviceId") == null || map.get("dataFlow") == null){
            logger.debug("设备id或者数据流错误！");
            return false;
        }

        String deviceId = map.get("deviceId").toString();
        String dataFlowCode = map.get("dataFlow").toString();
        String time = map.get("time").toString();
        String value = null;
        Object gpsTotalX = map.get("gpsTotalX");
        Object gpsTotalY = map.get("gpsTotalY");
        Object gpsTotalZ = map.get("gpsTotalZ");

        if(19 == time.length() && DateUtil.parseDate(time) != null){
            time = DateUtil.formatDateToString(DateUtil.parseDate(time), "yyyy-MM-dd HH:mm:ss");
        }else if((13 == time.length() || 24 == time.length()) && DateUtil.isDateFormat(time) != null){
            time = DateUtil.isDateFormat(time);
        }else{
            logger.debug("时间格式错误！");
            return false;
        }

        boolean gpsTotalIsNull = gpsTotalX != null && gpsTotalY != null && gpsTotalZ != null;
        if(dataFlowCode.startsWith("L1_GP") && gpsTotalIsNull){
            value = gpsTotalX + "," + gpsTotalY + "," + gpsTotalZ;
        }

        if(value == null && map.get("value") == null){
            logger.debug("数据格式错误！");
            return false;
        }else if(value == null){
            value = map.get("value").toString();
        }

        return saveData(deviceId, time, value);
    }

    /**
     * 将接收到的数据保存到数据库
     * @author zhanglifeng
     * @date 2021/04/13 13:26
     * @param id 设备id
     * @param dacTime 时间
     * @param value 数据值
     * @return boolean 是否发送成功
     */
    private boolean saveData(String id, String dacTime, String value) {
        boolean result = false;
        double dx, dy, dh;

        String innerDeviceId = uploadInfoService.getDeviceIdById(id);
        if(Strings.isBlank(innerDeviceId)){
            logger.debug("该设备不存在！");
            return false;
        }

        String[] dVs = value.split(",");
        dx = Double.parseDouble(dVs[0]) / 1000;
        dy = Double.parseDouble(dVs[1]) / 1000;
        dh = Double.parseDouble(dVs[2]) / 1000;

        DeviceData surfDeviceData = new DeviceData();
        surfDeviceData.setDeviceId(Integer.valueOf(innerDeviceId)).setDacTime(dacTime).setDx(dx).setDy(dy).setDh(dh);
        int insertResult;
        insertResult = baseMapper.insertData(surfDeviceData);
        if (1 == insertResult) {
            result = true;
        }
        return result;
    }
}
